﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using NHibernate;
using NHibernate.Criterion;
using NHibernate.Transaction;
using OpenGado.DATA.Entities;

namespace OpenGado.DATA
{
    /// <summary>
    /// Controls the behaviour of Product Object, 
    /// Provides methods to persist and retrieve values to / from db 
    /// 
    /// </summary>
    public class ProductDataControl
    {

        private static ProductDataControl productDataControl;
        private static  object lockProductControl = new object();
       // private FactoryHandler session;
        private ISession session;

        /// <summary>
        /// Make sure we always have an open session.
        /// </summary>
        public ISession Session
        {
            get
            {
                session = FactoryHandler.CreateFactory().OpenSession();
               
               
                return session;
            }
        }

        /// <summary>
        /// Returns instance of product data control object
        /// </summary>
        public static ProductDataControl Instance
        {
            get
            {
                lock(lockProductControl)
                    if (productDataControl == null)
                    {
                        productDataControl = new ProductDataControl();
                    }


                return productDataControl;
            }

        }
        /// <summary>
        /// Saves the product object to the database 
        /// and rethrows execption as session exception if any occured
        /// </summary>
        /// <param name="p"></param>
        /// <returns></returns>
        public void Save(Product p)
        {

            ITransaction transaction = null;
            ISession tSession; // temporary session holder 
            tSession = this.Session;
            transaction = tSession.BeginTransaction();

            
            try
            {

                tSession.SaveOrUpdate(p);
                transaction.Commit();
                

            }
            catch (Exception ex)
            {
                //TODO: Add loging on execption. 
                transaction.Rollback();
               
            }
            finally
            {
                tSession.Close();
            }
          
        }

        /// <summary>
        /// Deletes the product from the database.
        /// </summary>
        /// <param name="p"></param>
        public void Delete (Product p)
        {
            ITransaction transaction = null;
            ISession tSession; // temporary session holder 
            tSession = this.Session;
            
            try
            {

                transaction = tSession.BeginTransaction();

                tSession.Delete(p);
                transaction.Commit();

            }
            catch (Exception)
            {
                if (transaction != null) 
                    transaction.Rollback();
                throw;
            }
            finally
            {
                tSession.Close();
            }
        }

        public Product GetById(int productId)
        {
            ISession tsession = Session;
            Product product = tsession.Get<Product>(productId);
            tsession.Close();


            return product;
        }
        //TODO:  Needs to be written to get the products by name

      
        public  IList<Product> GetAll()
        {
            ISession tsession = Session;
            ICriteria criteria = tsession.CreateCriteria<Product>();
            IList<Product> products = criteria.List<Product>();

            tsession.Close();

           return products;

        }

        /// <summary>
        ///  gets product list matching a certain criteria.
        /// </summary>
        /// <param name="fieldName"></param>
        /// <param name="fieldValue"></param>
        /// <returns></returns>
        public IList<Product> Query(String fieldName, String fieldValue)
        {

            ISession tsession = Session;
            ICriteria criteria = tsession.CreateCriteria<Product>();


            switch (fieldName)
            {
                case"Project":
                    {
                        criteria.CreateCriteria("Project")
                            .Add(Restrictions.Like("Name", fieldValue + "%"));
                        break;

                    }
                case"Storage":
                    {
                        criteria.CreateCriteria("Storage")
                            .Add(Restrictions.Like("StoreName", fieldValue + "%"));
                        break;
                    }

                default:
                    criteria.Add(Restrictions.Like(fieldName, fieldValue + "%"));
                    break;
                    
            }
           
            IList<Product> products = criteria.List<Product>();

            tsession.Close();
            return products;

        }
    }
}
